package com.example.screenapppush

import android.hardware.display.DisplayManager
import android.media.MediaCodec
import android.media.MediaCodec.BufferInfo
import android.media.MediaCodec.CONFIGURE_FLAG_ENCODE
import android.media.MediaCodecInfo
import android.media.MediaFormat
import android.media.projection.MediaProjection
import android.util.Log
import java.nio.ByteBuffer
import java.util.*
import kotlin.experimental.and


class H264ScreenEncoder(var mediaProjection: MediaProjection) {


    var width = 1080
    var height = 1920
    lateinit var  mediaCodec:MediaCodec ;
    val NAL_I = 5
    val NAL_SPS = 7
    private var sps_pps_buf: ByteArray ?= null
    init {
        try {
             mediaCodec = MediaCodec.createEncoderByType("video/avc")
            var mediaFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, width, height)
            mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 20)
            mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 30)
            // 码率 码率一般指比特率,是表示单位时间内传送比特的数目。单位为比特/秒(bit/s或bps)
            // 码率 码率一般指比特率,是表示单位时间内传送比特的数目。单位为比特/秒(bit/s或bps)
            mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, width * height)
            mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
            mediaCodec.configure(mediaFormat, null, null, CONFIGURE_FLAG_ENCODE)
            var surface = mediaCodec.createInputSurface();
            mediaProjection.createVirtualDisplay("daidai", width, height, 2,  DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC, surface, null, null)
            mediaCodec.start()
        } catch (e: Exception) {
            Log.e("cuowu", "不支持编码")
        }
    }

    fun startEncode(callback:(byteArray: ByteArray)->Unit) {
        var buffInfo:BufferInfo = MediaCodec.BufferInfo();
        while (true) {
            var outBufferIndex = mediaCodec.dequeueOutputBuffer(buffInfo, 10000)

            if (outBufferIndex >= 0) {


                var buf:ByteBuffer? = mediaCodec.getOutputBuffer(outBufferIndex);
//                var  buf = ByteArray(byteBuffer!!.remaining())
//                if (byteBuffer != null) {
//                    byteBuffer.get(buf)
//                }

                buf?.let {
                    var offset = 4
                    if (buf[2].toInt() == 0x01) {
                        offset = 3
                    }
                    val type: Int = buf[offset].toInt() and  0x1F
                    //        sps  只会输出一份  非常宝贵
                    if (type == NAL_SPS) {
                        sps_pps_buf = ByteArray(buffInfo.size)
                        buf.get(sps_pps_buf)
                    } else if (NAL_I === type) {
                        val bytes = ByteArray(buffInfo.size)
                        buf.get(bytes) //45459
                        val newBuf = ByteArray(sps_pps_buf!!.size + bytes.size)
                        System.arraycopy(sps_pps_buf, 0, newBuf, 0, sps_pps_buf!!.size)
                        System.arraycopy(bytes, 0, newBuf, sps_pps_buf!!.size, bytes.size)
                        callback(newBuf)
                    } else {
                        val bytes = ByteArray(buffInfo.size)
                        buf.get(bytes)
                        callback(bytes)
                        Log.v("david", "视频数据  " + Arrays.toString(bytes))
                    }
                    // 写入文件
//                    writeFile(buf)
                    mediaCodec.releaseOutputBuffer(outBufferIndex,false)
                }


            }
        }
    }

    private fun writeFile(buf: ByteArray) {
//        val  path = Environment.getExternalStorageDirectory().absolutePath+"/screen.h264"
//        val  fileOutputStream  =  FileOutputStream(path,true)
//        fileOutputStream.write(buf)
//        fileOutputStream.close()
    }

}